# 第三方库
try:
    from flask import Flask,request
except ModuleNotFoundError:
    logger.info("缺少flask依赖！程序将尝试安装依赖！")
    os.system("pip3 install flask -i https://pypi.tuna.tsinghua.edu.cn/simple")
    os.execl(sys.executable, 'python3', __file__, *sys.argv)


from flask import Flask, render_template, request, redirect, url_for
from flask import send_from_directory, send_file

from datetime import datetime
import os
import logging
from logging.handlers import RotatingFileHandler
import json
from json import JSONEncoder
import cv2
import aircv as ac
import urllib.request
import numpy as np
import functools

app=Flask(__name__)

# POST方式获取参数
# res = request.form.get('name')
# res = request.form
# res = request.values
# res = request.data # 请求时需是json类型 在Headers中设置 Content-Type:application/json
# res = request.json # 请求时需是json类型
# res = request.get_data() # 请求时需是json类型
#
# # GET方式获取参数
# res = request.args.get('name')
# res = request.args

def return_msg(code=200, msg="ok", data=None):
    """
    返回数据
    """
    return {
        "code": code,
        "msg": msg,
        "data": data,
    }

def customStudentDecoder(studentDict):
    return namedtuple('X', studentDict.keys())(*studentDict.values())

def loadImage(ptImgs):
        for pt in ptImgs:
            img = readImage(pt['url'])
            trows,tcols = img.shape[:2]  #获得图片的宽度
            pt['img']=img
            pt['width']=trows
            pt['height']=tcols

def readImage(url, width=0, height=0):
    res = urllib.request.urlopen(url)
    img = np.asarray(bytearray(res.read()), dtype="uint8")
    img = cv2.imdecode(img, cv2.IMREAD_COLOR)
    if(width>0 and height>0):
        img = cv2.resize(img, (width,height))
    return img

def ptImage(largeImg, ptImgs):
    method = cv2.TM_SQDIFF_NORMED
    for i,p in enumerate(ptImgs):
        #小图
        small_image = p['img']
        result = cv2.matchTemplate(small_image, largeImg, method)
        # 需要最小平方差
        mn,_,mnLoc,_ = cv2.minMaxLoc(result)
        MPx,MPy = mnLoc #获得最小坐标的
        trows,tcols = small_image.shape[:2]  #获得图片的宽度
        # cv2.rectangle(largeImg, (MPx,MPy),(MPx+tcols,MPy+trows),(0,0,255),2)
        p['width'] = trows
        p['height'] = tcols
        p['loc'] = mnLoc
        #MPx,MPy = mnLoc #获得最小坐标的
    ptImgs.sort(key=functools.cmp_to_key(loc_sort))


def loc_sort(s1, s2):
    MPx1,MPy1 = s1['loc']
    MPx2,MPy2 = s2['loc']
    minW = s1['width']/2
    minH = s1['height']/2
    if(MPy1-MPy2>=minH):
        return 1
    elif(MPy2-MPy1>=minH):
        return -1
    else:
        if(MPx1-MPx2>=minW):
            return 1
        elif(MPx2-MPx1>=minW):
            return -1
        else:
            return 0

@app.route('/ccb/status',methods=['POST'])
def status():
    return return_msg()

@app.route('/ccb/jigsaw',methods=['POST'])
def jigsaw():
    try:
        result = request.get_json()
        if(result['status']=='success'):
            img = result['data']['img']
            thumb = result['data']['thumb']
            ptImgs =[]
            for n in thumb.keys():
                ptImgs.append({'n':n,'url':thumb.get(n)})
            loadImage(ptImgs)
            imgWidth = ptImgs[0]['width']*3
            imgHeight = ptImgs[0]['height']*3
            # print(f'原图拉伸至width:{imgWidth}, height:{imgHeight}')
            largeImg = readImage(img, imgWidth, imgHeight)
            ptImage(largeImg, ptImgs)
            nList = []
            for p in ptImgs:
                nList.append(p['n'])
            nResult =  ",".join(nList)
            print(f'拼图识别, 顺序：{nResult}')
            return return_msg(data=nResult)
        else:
            return return_msg(code=500, msg= '拼图识图失败！' )
    except Exception as e:
        print('拼图识图失败！', e)
        return return_msg(code=500, msg= f'拼图识图失败！{e}' )



if(__name__=='__main__'):
    # 设置日志的记录等级
    logging.basicConfig(level=logging.DEBUG) # 调试debug级
    # 创建日志记录器，指明日志保存的路径（前面的logs为文件的名字，需要我们手动创建，后面则会自动创建）、每个日志文件的最大大小、保存的日志文件个数上限。
    # file_log_handler = RotatingFileHandler("../logs/log", maxBytes=1024*1024*100, backupCount=10)
    file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024*1024*2, backupCount=10, encoding="utf-8", mode="a")
    # 创建日志记录的格式               日志等级    输入日志信息的文件名   行数       日志信息
    formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
    # 为刚创建的日志记录器设置日志记录格式
    file_log_handler.setFormatter(formatter)
    # 为全局的日志工具对象（flask app使用的）添加日志记录器
    logging.getLogger().addHandler(file_log_handler)
    # host='0.0.0.0' ，外网通过公网ip可访问， 如只想本机访问，改为本内网机IP即可
    app.run(host='0.0.0.0',port = '8998')



